package com.ruoyi.system.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.annotation.UserDataIsolation;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DataUtils;
import com.ruoyi.system.domain.Project;
import com.ruoyi.system.domain.ProjectAuthorize;
import com.ruoyi.system.domain.vo.QueryVo;
import com.ruoyi.system.mapper.ProjectMapper;
import com.ruoyi.system.service.ChinaAreaDataService;
import com.ruoyi.system.service.IProjectAuthorizeService;
import com.ruoyi.system.service.IProjectService;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import lombok.extern.slf4j.Slf4j;

import javax.validation.constraints.NotNull;

@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
@Slf4j
@Service
public class ProjectServiceImpl implements IProjectService
{
    @Autowired
    ProjectMapper projectMapper;

    @Autowired
    ISysDeptService sysDeptService;

    @Autowired
    ISysUserService sysUserService;

    @Autowired
    IProjectAuthorizeService projectAuthorizeService;

    @Override
    public Map<String, Object> parseInjectionItem(JSONObject item, Long companyId) {
        Map<String, Object> parsed = new HashMap<>();
        try {
            String name = item.getString("名称");
            if (name == null) {
                parsed.put("message", "名称不能为空");
                return parsed;
            }
            String code = item.getString("合同号");
            if (code == null) {
                parsed.put("message", "合同号不能为空");
                return parsed;
            }
            String peerName = item.getString("客户名称");
            if (peerName == null) {
                parsed.put("message", "客户名称不能为空");
                return parsed;
            }
            Integer type = item.getInteger("项目类型：1内部项目2外部项目3测试项目");
            if (type == null) {
                parsed.put("message", "项目类型不能为空");
                return parsed;
            }
            SysDept sysDept= sysDeptService.lookupByName(peerName, companyId);
            if (sysDept != null) {
                if (sysDept.getAncestors().indexOf("0," + companyId.toString()) < 0) {
                    parsed.put("message", String.format("客户 %s 不存在", peerName));
                    return parsed;
                }
                if (!sysDeptService.checkIsCustomer(sysDept.getDeptId())) {
                    parsed.put("message", String.format("%s 不是客户", peerName));
                    return parsed;
                } else {
                    if (sysDept.getIsCustomer() == 0) {
                        parsed.put("message", String.format("%s 不是客户公司全称", peerName));
                        return parsed;
                    }
                }
            } else {
                parsed.put("message", String.format("客户 %s 不存在", peerName));
                return parsed;
            }
            String peerCode = item.getString("客户合同号");
            if (peerCode == null) {
                parsed.put("message", "客户合同号不能为空");
                return parsed;
            }
            String rawInputTime = item.getString("统计时间");
            if (rawInputTime == null || rawInputTime.isBlank()) {
                parsed.put("message", String.format("统计时间未填写"));
                return parsed;
            }
            Integer dateOffset = -1;
            try {
                dateOffset = Integer.parseInt(rawInputTime);
            } catch (Exception e) {}
            if (dateOffset < 0) {
                parsed.put("message", String.format("统计时间 %s 不正确", rawInputTime));
                return parsed;
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date inputTime = sdf.parse("1900-01-01");
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(inputTime);
            calendar.set(Calendar.DATE, dateOffset);
            inputTime = calendar.getTime();
            String amount = item.getString("合同金额");
            String salesman = item.getString("责任人");
            String region = item.getString("行政区");
            String areaCode = null;
            if (region == null) {
                areaCode = "";
            } else {
                try {
                    areaCode = ChinaAreaDataService.nameToCode(region);
                } catch (Exception e) {}
            }
            String address = item.getString("地址");
            if (address == null) {
                address = "";
            }
            String lng = item.getString("经度");
            String lat = item.getString("纬度");
            String remark = item.getString("备注");
            if (remark == null) {
                remark = "";
            }
            Project project = new Project();
            project.setName(name);
            project.setCode(code);
            project.setDeptId(sysDept.getDeptId().intValue());
            project.setPeerCode(peerCode);
            if (amount != null) {
                project.setAmount(Double.parseDouble(amount));
            }
            project.setSalesman(salesman);
            project.setIsOn(1);
            project.setInputTime(inputTime);
            project.setRemark(remark);
            project.setAreaCode(areaCode);
            project.setAddress(address);
            project.setType(type);
            if (lng != null) {
                project.setLng(Double.parseDouble(lng));
            }
            if (lat != null) {
                project.setLat(Double.parseDouble(lat));
            }
            parsed.put("project", project);
        } catch (Exception e) {
            log.info("",e);
            StackTraceElement[] traces = e.getStackTrace();
            for (StackTraceElement trace : traces) {
                log.debug(trace.toString());
            }
        }
        return parsed;
    }

    @Override
    @UserDataIsolation(tableAlias = "tbl_project")
    public Map<String, Object> findExistance(Project project) {
        return projectMapper.findExistance(project);
    }

    @Override
    public Integer create(Project project) {
        Integer id = null;
        //验证项目是否属于客户
        Integer deptId = project.getDeptId();
        SysDept sysDept = sysDeptService.selectDeptById(Convert.toLong(deptId));
        if (sysDept.getIsCustomer() != 1){
            throw new CustomException("客户名称应选择客户公司");
        }
        try {
            Integer affected = projectMapper.create(project);
            if (affected > 0) {
                id = project.getId();
                ProjectAuthorize authorize = new ProjectAuthorize();
                authorize.setProjectId(id);
                authorize.setCompanyId(project.getCompanyId());
                authorize.setCreateTime(project.getCreateTime());
                authorize.setCreateBy(project.getCreateBy());
                authorize.setIsOwner(1);
                authorize.setUserId(sysUserService.selectUserByUserName(project.getCreateBy()).getUserId().intValue());
                projectAuthorizeService.add(authorize);
            }
        } catch (Exception e) {
            log.info("",e);
            StackTraceElement[] traces = e.getStackTrace();
            for (StackTraceElement trace : traces) {
                log.debug(trace.toString());
            }
            id = null;
        }
        return id;
    }

    @Override
    public List<Project> index(QueryVo queryVo) {
        List<Project> projects = projectMapper.index(queryVo);
        for (Project project : projects) {
            project.setAreaName(ChinaAreaDataService.codeToName(project.getAreaCode()));
        }
        return projects;
    }

    @Override
    @UserDataIsolation(tableAlias = "p")
    public Project retrieve(QueryVo queryVo) {
        Project project = projectMapper.retrieve(queryVo);
        if (project != null) {
            project.setAreaName(ChinaAreaDataService.codeToName(project.getAreaCode()));
        }
        return project;
    }

    @Override
    @UserDataIsolation(tableAlias = "tbl_project")
    public Boolean update(Project project) {
        //验证项目是否属于客户
        Integer deptId = project.getDeptId();
        SysDept sysDept = sysDeptService.selectDeptById(Convert.toLong(deptId));
        if (sysDept.getIsCustomer() != 1){
            throw new CustomException("客户名称应选择客户公司");
        }
        Boolean done = false;
        try {
            Integer affected = projectMapper.update(project);
            if (affected > 0) {
                done = true;
            }
        } catch (Exception e) {
            log.info("",e);
            StackTraceElement[] traces = e.getStackTrace();
            for (StackTraceElement trace : traces) {
                log.debug(trace.toString());
            }
        }
        return done;
    }

    @Override
    @UserDataIsolation(tableAlias = "tbl_project")
    public List<Map<String, Object>> summary(QueryVo queryVo, Map<String, Object> options) {
        List<Map<String, Object>> summary = null;
        try {
            Map<String, Object> summaryKV = projectMapper.summary(queryVo);
            summary = DataUtils.KVtoList(summaryKV, options);
        } catch (Exception e) {
            log.info("",e);
            StackTraceElement[] traces = e.getStackTrace();
            for (StackTraceElement trace : traces) {
                log.debug(trace.toString());
            }
        }
        return summary;
    }

    @Override
    @UserDataIsolation(tableAlias = "p")
    public List<Map<String, Object>> deviceCount(QueryVo queryVo, Map<String, Object> options) {
        List<Map<String, Object>> deviceCount = new ArrayList<>();
        try {
            Map<String, Object> regulatedOptions = new HashMap<>();
            regulatedOptions.put("name", "label");
            regulatedOptions.put("count", "value");
            List<Map<String, Object>> rawDeviceCount = projectMapper.deviceCount(queryVo);
            for (Map<String, Object> item : rawDeviceCount) {
                Map<String, Object> regulated = DataUtils.KVconvertKey(item, regulatedOptions);
                deviceCount.add(DataUtils.KVconvertKey(regulated, options));
            }
        } catch (Exception e) {
            log.info("",e);
            StackTraceElement[] traces = e.getStackTrace();
            for (StackTraceElement trace : traces) {
                log.debug(trace.toString());
            }
        }
        return deviceCount;
    }

    @Override
    @UserDataIsolation(tableAlias = "p")
    public List<Map<String, Object>> configuredTerminalCount(QueryVo queryVo, Map<String, Object> options) {
        List<Map<String, Object>> terminalCount = new ArrayList<>();
        try {
            Map<String, Object> regulatedOptions = new HashMap<>();
            regulatedOptions.put("name", "label");
            regulatedOptions.put("count", "value");
            List<Map<String, Object>> rawTerminalCount = projectMapper.configuredTerminalCount(queryVo);
            for (Map<String, Object> item : rawTerminalCount) {
                Map<String, Object> regulated = DataUtils.KVconvertKey(item, regulatedOptions);
                terminalCount.add(DataUtils.KVconvertKey(regulated, options));
            }
        } catch (Exception e) {
            log.info("",e);
            StackTraceElement[] traces = e.getStackTrace();
            for (StackTraceElement trace : traces) {
                log.debug(trace.toString());
            }
        }
        return terminalCount;
    }

    @Override
    @UserDataIsolation(tableAlias = "tbl_project")
    public List<Map<String, Object>> valueByMonth(QueryVo queryVo, Map<String, Object> options) {
        List<Map<String, Object>> values = new ArrayList<>();
        try {
            List<String> months = null;
            Date start = queryVo.filters.getDate("start");
            if (start != null) {
                months = new ArrayList<>();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(start);
                Date now = new Date();
                while (calendar.getTime().before(now)) {
                    months.add(sdf.format(calendar.getTime()));
                    calendar.add(Calendar.MONTH, 1);
                }
            }
            Map<String, Object> regulatedOptions = new HashMap<>();
            regulatedOptions.put("month", "label");
            regulatedOptions.put("value", "value");
            List<Map<String, Object>> monthValues = projectMapper.valueByMonth(queryVo);
            if (months != null) {
                for (String month : months) {
                    Boolean found = false;
                    for (Map<String, Object> item : monthValues) {
                        if (item.get("month").toString().equals(month)) {
                            Map<String, Object> regulated = DataUtils.KVconvertKey(item, regulatedOptions);
                            values.add(DataUtils.KVconvertKey(regulated, options));
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        Map<String, Object> item = new HashMap<>();
                        item.put("month", month);
                        item.put("value", 0);
                        Map<String, Object> regulated = DataUtils.KVconvertKey(item, regulatedOptions);
                        values.add(DataUtils.KVconvertKey(regulated, options));
                    }
                }
            } else {
                for (Map<String, Object> item : monthValues) {
                    Map<String, Object> regulated = DataUtils.KVconvertKey(item, regulatedOptions);
                    values.add(DataUtils.KVconvertKey(regulated, options));
                }
            }
        } catch (Exception e) {
            log.info("",e);
            StackTraceElement[] traces = e.getStackTrace();
            for (StackTraceElement trace : traces) {
                log.debug(trace.toString());
            }
        }
        return values;
    }

    @Override
    @UserDataIsolation(tableAlias = "tbl_project")
    public List<Map<String, Object>> statusByMonth(QueryVo queryVo, Map<String, Object> options) {
        List<Map<String, Object>> result = new ArrayList<>();
        try {
            Set<String> months = null;
            Date start = queryVo.filters.getDate("start");
            if (start != null) {
                months = new TreeSet<>();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(start);
                Date now = new Date();
                while (calendar.getTime().before(now)) {
                    months.add(sdf.format(calendar.getTime()));
                    calendar.add(Calendar.MONTH, 1);
                }
            }
            List<Map<String, Object>> monthValues = projectMapper.statusByMonth(queryVo);
            Map<String, Map<String, Integer>> monthMap = new HashMap<>();
            for (Map<String, Object> item : monthValues) {
                String month = item.get("month").toString();
                Map<String, Integer> counts = monthMap.get(month);
                if (counts == null) {
                    counts = new HashMap<>();
                    counts.put("open", 0);
                    counts.put("close", 0);
                    counts.put("total", 0);
                    monthMap.put(month, counts);
                }
                Integer isOn = Integer.parseInt(item.get("is_on").toString());
                Integer count = Integer.parseInt(item.get("count").toString());
                if (isOn > 0) {
                    counts.put("open", count);
                } else {
                    counts.put("close", count);
                }
                counts.put("total", counts.get("total") + count);
            }
            if (months == null) {
                months = monthMap.keySet();
            }
            for (String month : months) {
                Map<String, Integer> counts = monthMap.get(month);
                Map<String, Object> resultItem = new HashMap<>();
                resultItem.put("月份", month);
                if (counts == null) {
                    resultItem.put("进行中", 0);
                    // resultItem.put("已完成", 0);
                    resultItem.put("总数", 0);
                } else {
                    resultItem.put("进行中", counts.get("open"));
                    // resultItem.put("已完成", counts.get("close"));
                    resultItem.put("总数", counts.get("total"));
                }
                result.add(resultItem);
            }
        } catch (Exception e) {
            log.info("",e);
            StackTraceElement[] traces = e.getStackTrace();
            for (StackTraceElement trace : traces) {
                log.debug(trace.toString());
            }
        }
        return result;
    }

    @Override
    public boolean checkProjectCreateByIsCustomer(QueryVo queryVo) {
        Integer projectId = queryVo.filters.getInteger("project_id");
        queryVo.filters.put("id",projectId);
        Project retrieve = projectMapper.retrieve(queryVo);
        if (retrieve == null){
            throw new CustomException("没有查询到项目信息");
        }
        String createBy = retrieve.getCreateBy();
        SysUser sysUser = sysUserService.selectUserByUserName(createBy);
        return sysDeptService.checkIsCustomer(sysUser.getDeptId());
    }
}
